home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / GRAPHICS.SWG / 0151_Sprite Engine.pas < prev    next >
Pascal/Delphi Source File  |  1995-03-03  |  16KB  |  516 lines

  1. {
  2. >I am making a computer game using pascal and a 640x480x16 resolution,
  3. >using Jordan Hargrafix's SVGABG16.BGI driver, and I want to use the
  4. >setactivepage/setvisualpage commands to "hide" the screen as it is being
  5. >redrawn, and then show it again to give the effect of super fast screen
  6. >refresh (i.e. so fast, you can't see it)
  7.  
  8. I don't havce time to find out what you mean exactly.
  9. This unit redraws sprites, and doesn't display them until
  10. ShowVirtualScreen is activated.
  11. }
  12. unit Sprites;
  13. { Basically a simple and effective spriteengine for use with Turbo }
  14. { Pascal 6.0. (Does not require the GRAPH unit..)                  }
  15. {                                                                  }
  16. { Designed for use with MCGA, VGA and compatibles. Works in mode   }
  17. { mode $13 (320x200 with 256 simultaneously colours.               }
  18. {                                                                  }
  19. { Written by:                                                      }
  20. {            Marius Kjeldahl                                       }
  21. {            Stud. post 104                                        }
  22. {            N-7034 Trondheim - NTH                                }
  23. {            Norway                                                }
  24. {            Ph. +47 7 58 91 11                                    }
  25. {            e-mail: mariusk@lise.unit.no                          }
  26. {                    (at NTH - Norwegian Institute of Technology ) }
  27. {                    (dept. of Business and Information Technolgy) }
  28. {                                                                  }
  29. { These routines are being distributed as shareware. To be used in,}
  30. { or as part of any commercial product, you have to become a       }
  31. { registered user. As a registered user you will receive upgrades  }
  32. { and rights to distribute these routines with your products.      }
  33. { To become a registered user, you will have to send a letter with }
  34. { who you are and what product(s) will use these routines and      }
  35. { make US$39 payable to the author (cheque or money..).            }
  36. {                                                                  }
  37. {                                                                  }
  38. { If you have any suggestions or comments please do not hesitate   }
  39. { to contact me. Have fun...                                       }
  40. {                                                                  }
  41. { Future plans for enhancements: interrupt driven, faster rep      }
  42. { movsw for sprites, built in animation, screen region scrolling   }
  43. { and more..                                                       }
  44.  
  45. interface
  46. uses
  47.   Dos;
  48. const
  49.   MaxSprites = 14; { Maximum number of sprites activated simultaneously }
  50.   MaxDim = 80*10;  { Dimensions of largest sprite to be used (x*y)      }
  51. type
  52.   ScreenTypePointer = ^ScreenType;       { Pointer to a virtual screen  }
  53.   ScreenType = array [1..64000] of byte; { Array to hold virtual screen }
  54.   SpriteType = record                    { Misc. sprite data            }
  55.                  oldx, oldy,             { - old location               }
  56.                  x, y : integer;         { - current location           }
  57.                  w, h : byte;            { - width and height           }
  58.                  SpriteData,             { - spriteimage                }
  59.                  Buffer : array [0..MaxDim-1] of byte; { spritebackgr.  }
  60.                  Active : boolean;       { - currently active           }
  61.                  ix, iy : integer;       { - sprite increment           }
  62.                                          {   (not currently used)       }
  63.                end;
  64. var
  65.   Sprite : array [1..MaxSprites] of SpriteType; { Array of sprites      }
  66.   Virtual_Screen : ScreenTypePointer;    { Pointer to virtual screen    }
  67.  
  68.   procedure DrawSprites;
  69.   { Saves background and draws all currently active sprites at their    }
  70.   { current location.                                                   }
  71.  
  72.   procedure LoadSprite (Num : byte; FileName : string);
  73.   { Loads spritedata from ordinary text file. Examine the .SPR files    }
  74.   { for further details. Use .CEL files instead if you've have          }
  75.   { purchased AutoDesk Animator...                                      }
  76.  
  77.   procedure SetMode (Mode : word);
  78.   { Sets screen mode. Use $13 for use with sprites                      }
  79.  
  80.   procedure ShowVirtualScreen ;
  81.   { Copies the VirtualScreen to the users screen. Any changes done with }
  82.   { the sprites and/or their position will NOT be visible until this    }
  83.   { routine has been called!                                            }
  84.  
  85.   procedure LoadCOL (FileName : string);
  86.   { Loads a file containing the palette desc. of the 256 colours and    }
  87.   { programs the VGA/MCGA to use these palette. It uses AutoDesk        }
  88.   { Animators file format - so you can use Animator to select colors and}
  89.   { then save the palette in Animators ordinary .COL file.              }
  90.   { For those without Animator (you should not be..) the file format is }
  91.   { simple. Each colour (from 0 to 255) has three bytes which containts }
  92.   { red, green and blue values. First in the file comes (usually)       }
  93.   { 0,0,0 - black and so on until the last colour.                      }
  94.  
  95.   procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  96.   { Directly loads a CEL to the location pointed to by ScrPtr.          }
  97.   { This routine uses AutoDesk Animators file format. This means you    }
  98.   { can use Animators excellent drawing tools to design you sprites and }
  99.   { save them in a ordinary .CEL file.                                  }
  100.   { For those without Animator; here is a short desc. of the format:    }
  101.   { The first 800 bytes is Animators header. It does include various    }
  102.   { information like it's own colours palette, width and height.        }
  103.   { However this version skips all that information and just reads the  }
  104.   { image data into the location pointed to by ScrPtr. Remember to      }
  105.   { set the sprites width and height too! (It is NOT read you of the    }
  106.   { .CEL file in this release..                                         }
  107.  
  108.   procedure DisableAllSprites;
  109.   { Disables all sprites. But this routine does not restore the screen  }
  110.   { image (compare with HideSprites..                                   }
  111.  
  112.   procedure HideSprites;
  113.   { Disables all sprites. Basically same as DisableAllSprites, but this }
  114.   { routine also recovers the "original" screen image.                  }
  115.  
  116.   procedure FillBox (x1, y1, x2, y2 : integer; b : byte);
  117.   { Draws a coloured box with upper left corner x1,y1 and lower right   }
  118.   { corner x2,y2.                                                       }
  119.  
  120.   procedure CopySprite (var Sprite : SpriteType; x1, y1 : integer);
  121.   { "Stamps" a copy of any sprite at the chosen location x1,y1.         }
  122.   { Use this routine if you want to put the image there, but do not plan}
  123.   { to animate in anyway..                                              }
  124.  
  125.   procedure WaitForVerticalRetrace;
  126.   { Waits for vertical retrace. Will be used in further releases..      }
  127.  
  128. implementation
  129.  
  130. procedure CopySprite (var Sprite : SpriteType; x1, y1 : integer); assembler;
  131. label
  132.   _Redraw, _DrawLoop, _Exit, _LineLoop, _NextLine, _Store, _NoPaint;
  133.   asm
  134.     push  ds
  135.     push  es
  136.     lds   si,Sprite
  137.     mov   ax,x1     { ax = x }
  138.     mov   bx,y1     { bx = y }
  139. _Redraw:
  140.     push  ax
  141.     push  bx
  142.     mov   ax,word(Virtual_Screen+2)
  143.     mov   es,ax         { ES=A000h }
  144.     pop   bx            { ax = y }
  145.     mov   ax,320
  146.     mul   bx            { ax = y * 320 }
  147.     pop   bx            { ax = x }
  148.     add   ax,bx         { bx = bx + ax dvs. skjermadr.. }
  149.     mov   di,ax         { di = skjermadr. }
  150.     mov   dl,[si+9]     { dl = height of sprite }
  151.     xor   ch,ch
  152.     mov   cl,[si+8]     { cx = width of sprite }
  153.     add   si,10         { si = start of spritedata }
  154.     cld
  155. _DrawLoop:
  156.     push  di            { store y adr. for later }
  157.     push  cx            { store width }
  158. _LineLoop:
  159.     mov   bl,byte ptr [si]
  160.     or    bl,bl
  161.     jnz   _Store
  162. _NoPaint:
  163.     inc    si
  164.     inc    di
  165.     loop   _LineLoop
  166.     jmp    _NextLine
  167. _Store:
  168. {    test   byte ptr [es:di],1
  169.     jz     _NoPaint}
  170.     movsb
  171.     loop  _LineLoop
  172. _NextLine:
  173.     pop   cx
  174.     pop   di
  175.     dec   dl
  176.     jz    _Exit
  177.     add   di,320        { di = next line of sprite }
  178.     jmp   _DrawLoop
  179. _Exit:
  180.     pop   es
  181.     pop   ds
  182.   end;
  183.  
  184. procedure DrawSprite (var Sprite : SpriteType); assembler;
  185. label
  186.   _Redraw, _DrawLoop, _Exit, _LineLoop, _NextLine, _Store, _NoPaint;
  187.   asm
  188.     push  ds
  189.     push  es
  190.     lds   si,Sprite
  191.     mov   ax,[si+4]     { ax = x }
  192.     mov   bx,[si+6]     { bx = y }
  193.     cmp   ax,[si]        {if x <> oldx then _Redraw}
  194.     jne   _Redraw       {
  195.     cmp   bx,[si+2]
  196.    je    _Exit         { if (x=oldx) and (y=oldy) then exit }
  197. _Redraw:
  198.     mov   [si],ax       { oldx = x }
  199.     mov   [si+2],bx     { oldy = y }
  200.     push  ax
  201.     push  bx
  202.     mov   ax,word(Virtual_Screen+2)
  203.     mov   es,ax         { ES=A000h }
  204.     pop   bx            { ax = y }
  205.     mov   ax,320
  206.     mul   bx            { ax = y * 320 }
  207.     pop   bx            { ax = x }
  208.     add   ax,bx         { bx = bx + ax dvs. skjermadr.. }
  209.     mov   di,ax         { di = skjermadr. }
  210.     mov   dl,[si+9]     { dl = height of sprite }
  211.     xor   ch,ch
  212.     mov   cl,[si+8]     { cx = width of sprite }
  213.     add   si,10         { si = start of spritedata }
  214.     cld
  215. _DrawLoop:
  216.     push  di            { store y adr. for later }
  217.     push  cx            { store width }
  218. _LineLoop:
  219.     mov   bl,byte ptr [si]
  220.     or    bl,bl
  221.     jnz   _Store
  222. _NoPaint:
  223.     inc    si
  224.     inc    di
  225.     loop   _LineLoop
  226.     jmp    _NextLine
  227. _Store:
  228. {    test   byte ptr [es:di],1
  229.     jz     _NoPaint}
  230.     movsb
  231.     loop  _LineLoop
  232. _NextLine:
  233.     pop   cx
  234.     pop   di
  235.     dec   dl
  236.     jz    _Exit
  237.     add   di,320        { di = next line of sprite }
  238.     jmp   _DrawLoop
  239. _Exit:
  240.     pop   es
  241.     pop   ds
  242.   end;
  243.  
  244. procedure SaveSpriteBackground (var Sprite : Spritetype); assembler;
  245. label
  246.   _Redraw, _DrawLoop, _Exit;
  247.   asm
  248.     push  ds
  249.     push  es
  250.     les   di,Sprite
  251.     mov   ax,es:[di+4]     { ax = x }
  252.     mov   bx,es:[di+6]     { bx = y }
  253.     push  ax
  254.     push  bx
  255.     mov   ax,word(Virtual_Screen+2)
  256.     mov   ds,ax         { DS=A000h }
  257.     pop   bx            { bx = y }
  258.     mov   ax,320
  259.     mul   bx            { ax = y * 320 }
  260.     pop   bx            { bx = x }
  261.     add   ax,bx         { ax = ax + bx dvs. skjermadr.. }
  262.     mov   si,ax         { si = skjermadr. }
  263.     mov   dl,es:[di+9]     { dl = height of sprite }
  264.     xor   ch,ch
  265.     mov   cl,es:[di+8]     { cx = width of sprite }
  266.     add   di,10+MaxDim  { di = start of screenbuffer }
  267.     cld
  268. _DrawLoop:
  269.     push  si            { store y adr. for later }
  270.     push  cx            { store width }
  271.     rep   movsb
  272.     pop   cx
  273.     pop   si
  274.     dec   dl
  275.     jz    _Exit
  276.     add   si,320        { di = next line of sprite }
  277.     jmp   _DrawLoop
  278. _Exit:
  279.     pop   es
  280.     pop   ds
  281.   end;
  282.  
  283. procedure FillBox (x1, y1, x2, y2 : integer; b : byte); assembler;
  284. label
  285.   _l1;
  286. asm
  287.   push  ds
  288.   push  es
  289.   mov   ax,word(Virtual_Screen+2)
  290.   mov   es,ax
  291.   mov   ax,y1
  292.   mov   bx,320
  293.   mul   bx
  294.   mov   di,ax
  295.   add   di,x1
  296.   mov   ax,y1
  297.   mov   dx,y2
  298.   sub   dx,ax
  299.   inc   dx
  300.  
  301.   mov   ax,x1
  302.   mov   cx,x2
  303.   sub   cx,ax { cx contains number of bytes across }
  304.   inc   cx
  305.   mov   al,b
  306.   cld
  307. _l1:
  308.   push  di
  309.   push  cx
  310.   rep   stosb
  311.   pop   cx
  312.   pop   di
  313.   add   di,320
  314.   dec   dx
  315.   jnz   _l1
  316.   pop   es
  317.   pop   ds
  318. end;
  319.  
  320.  
  321. procedure RestoreSpriteBackground (var Sprite : Spritetype); assembler;
  322. label
  323.   _Redraw, _DrawLoop, _Exit, _LineLoop;
  324.   asm
  325.     push  ds
  326.     push  es
  327.     lds   si,Sprite
  328.     mov   ax,[si]     { ax = x }
  329.     mov   bx,[si+2]     { bx = y }
  330.     push  ax
  331.     push  bx
  332.     mov   ax,word(Virtual_Screen+2)
  333.     mov   es,ax         { ES=A000h }
  334.     pop   bx            { ax = y }
  335.     mov   ax,320
  336.     mul   bx            { ax = y * 320 }
  337.     pop   bx            { ax = x }
  338.     add   ax,bx         { bx = bx + ax dvs. skjermadr.. }
  339.     mov   di,ax         { di = skjermadr. }
  340.     mov   dl,[si+9]     { dl = height of sprite }
  341.     xor   ch,ch
  342.     mov   cl,[si+8]     { cx = width of sprite }
  343.     add   si,10+MaxDim         { si = start of spritedata }
  344.     cld
  345. _DrawLoop:
  346.     push  di            { store y adr. for later }
  347.     push  cx            { store width }
  348.     rep   movsb
  349.     pop   cx
  350.     pop   di
  351.     dec   dl
  352.     jz    _Exit
  353.     add   di,320        { di = next line of sprite }
  354.     jmp   _DrawLoop
  355. _Exit:
  356.     pop   es
  357.     pop   ds
  358.   end;
  359.  
  360. procedure DrawSprites;
  361. var
  362.   I : byte;
  363. begin
  364.   for I := MaxSprites downto 1 do
  365.     if (Sprite[I].Active) and (Sprite [I].oldx <> -1) then
  366.       RestoreSpriteBackground (Sprite [I]);
  367.   for I := 1 to MaxSprites do begin
  368.     if Sprite [I].Active then begin
  369.       SaveSpriteBackground (Sprite [I]);
  370.       DrawSprite (Sprite [I]);
  371.     end;
  372.   end;
  373. end;
  374.  
  375. procedure HideSprites;
  376. var
  377.   I : byte;
  378. begin
  379.   for I := MaxSprites downto 1 do
  380.     if (Sprite [I].oldx <> -1) then begin
  381.       RestoreSpriteBackground (Sprite [I]);
  382.       Sprite [I].oldx := -1;
  383.     end;
  384. end;
  385.  
  386. procedure SetMode (Mode : word);
  387. begin
  388.   asm
  389.     mov ax,Mode;
  390.     int 10h
  391.   end;
  392. end;
  393.  
  394. procedure LoadSprite (Num : byte; FileName : string);
  395. var
  396.   Fil : text;
  397.   fx, fy : word;
  398. begin
  399.   assign (Fil, FileName);
  400.   reset (Fil);
  401.   fillchar (Sprite [Num], sizeof (Sprite[1]), 0);
  402.   with Sprite [Num] do begin
  403.     oldx := integer ($FFFF);
  404.     readln (Fil, w, h);          {integer-32768}
  405.     for fy := 1 to h do begin
  406.       for fx := 1 to w do
  407.         read (Fil, SpriteData [pred (fy) * w + pred (fx)]);
  408.       readln (fil);
  409.     end;
  410.   end;
  411.   close (Fil);
  412. end;
  413.  
  414. procedure LoadCOL (FileName : string);
  415. type
  416.   DACType = array [0..255] of record
  417.                                 R, G, B : byte;
  418.                               end;
  419. var
  420.   DAC : DACType;
  421.   Fil : file of DACType;
  422.   I : integer;
  423.   Regs : Registers;
  424. begin
  425.   assign (Fil, FileName);
  426.   reset (Fil);
  427.   read (Fil, DAC);
  428.   close (Fil);
  429.   for I := 0 to 255 do begin
  430.     with Regs do begin
  431.       AX := $1010;
  432.       BX := I;
  433.       DH := DAC [I].R;
  434.       CH := DAC [I].G;
  435.       CL := DAC [I].B;
  436.     end;
  437.     Intr ($10, Regs);
  438.   end;
  439. end;
  440.  
  441. procedure WaitForVerticalRetrace; assembler;
  442. label
  443.   l1, l2;
  444. asm
  445.     cli
  446.     mov dx,3DAh
  447. l1:
  448.     in al,dx
  449.     and al,08h
  450.     jnz l1
  451. l2:
  452.     in al,dx
  453.     and al,08h
  454.     jz  l2
  455.     sti
  456. end;
  457.  
  458. procedure ShowVirtualScreen; assembler;
  459.     asm
  460.       push ds
  461.       push es
  462.       xor  si,si
  463.       xor  di,di
  464.       cld
  465.       mov  ax,word(Virtual_Screen + 2)
  466.       mov  ds,ax
  467.       mov  ax,0A000h
  468.       mov  es,ax
  469.       mov  cx,7D00h
  470.       rep  movsw
  471.       pop  es
  472.       pop  ds
  473.     end;
  474.  
  475. procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  476. var
  477.   Fil : file;
  478.   Buf : array [1..1024] of byte;
  479.   BlocksRead, Count : word;
  480. begin
  481.   assign (Fil, FileName);
  482.   reset (Fil, 1);
  483.   BlockRead (Fil, Buf, 800);
  484.   Count := 0; BlocksRead := $FFFF;
  485.   while (not eof (Fil)) and (BlocksRead <> 0) do begin
  486.     BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024,
  487. BlocksRead);
  488.     Count := Count + 1024;
  489.   end;
  490.   close (Fil);
  491. end;
  492.  
  493. procedure DisableAllSprites;
  494. var
  495.   I : integer;
  496. begin
  497.   for I := 1 to MaxSprites do
  498.     with Sprite [I] do begin
  499.       OldX := -1;
  500.       Active := FALSE;
  501.     end;
  502. end;
  503.  
  504. var
  505.   Dum : ^byte;
  506. begin
  507.   DisableAllSprites;
  508.   repeat
  509.     new (Virtual_Screen);
  510.     if ofs (Virtual_Screen^) <> 0 then begin
  511.       dispose (Virtual_Screen);
  512.       new (Dum);
  513.     end;
  514.   until ofs (Virtual_Screen^) = 0;
  515. end.
  516.